/**
* @file ddas_assimilator.C
* @author Max Rupplin
* @date 4-20-08
*/

#include "ddas_definitions.h"
#include "DDAS_XML_Handler.hpp"
#include "DDAS_Assimilation_Handler.hpp"

#include "config.h"
#include <cstdio>
#include <iostream>

#include "boinc_db.h"
#include "sched_msgs.h"
#include "sched_util.h"
#include "assimilate_handler.h"
#include "validate_util.h"

#include <backend_lib.h>
#include <parse.h>

using std::vector;
using std::string;
using namespace std;

/**
* A function that determines what should be done with a workunit (and its data) after it has been validated. The assimilator copies the canonical result's output file and data contained therein into the science database.
* 
* @param wu The workunit in question
* @param results A vector of results related to the workunit 'wu'
* @param canonical_result The validated result - see http://www.boinc-wiki.info/Canonical_Result
* @return returns 0 if successful, 'retval' (BOINC defined) otherwise 
*/
int assimilate_handler(WORKUNIT& wu, vector<RESULT>& results, RESULT& canonical_result)
{
	#ifdef DEBUG_MODE
        cout<<"assimilate_handler called..."<<endl;
        #endif

	//if this is a canonical result
	if(wu.canonical_resultid)
	{
		//responsible for XML manipulation
        	DDAS_XML_Handler* xml_handler = new DDAS_XML_Handler();

		//responsible for assimilation tasks
        	DDAS_Assimilation_Handler* assimilation_handler = new DDAS_Assimilation_Handler();

		//create the struct to hold the data from the output file
		DDAS_Client_Result_Data* result_data;


		//parse data file for DDAS_CLIENT_RESULT_DATA			
		result_data = xml_handler->parseResultData( canonical_result );

		//fetch job ID for a given workunit
		int jobID = assimilation_handler->queryJobID( wu );
		
		//check if successful
		if( jobID <= 0 )
		{
                	log_messages.printf
                	(
                        	SCHED_MSG_LOG::MSG_CRITICAL,
                        	"Unable to find a job ID for WORKUNIT #%u\n",
                        	wu.id
                	);		
	
			//return error
			return 1;	
		}

		
		//insert job ID, workunit ID and canonical result ID into science database
		if( assimilation_handler->insertMappingData( wu.id, canonical_result.id, jobID )==0 )
		{
                        log_messages.printf
                        (
                                SCHED_MSG_LOG::MSG_CRITICAL,
                                "Unable to complete insertMappingData for RESULT #%u\n",
                                canonical_result.id
                        );
		}
		else
		{
                        log_messages.printf
                        (
                                SCHED_MSG_LOG::MSG_DEBUG,
                                "Successfully completed insertMappingData for RESULT #%u\n",
                                canonical_result.id
                        );
		}
		
		//insert the output file (client result data) into science database
		if( assimilation_handler->insertOutputFile( result_data, canonical_result, jobID )==0 )
		{
                        log_messages.printf
                        (
                                SCHED_MSG_LOG::MSG_CRITICAL,
                                "Unable to complete insertOutputFile for RESULT #%u\n",
                                canonical_result.id
                        );
		}
		else
		{
                        log_messages.printf
                        (
                                SCHED_MSG_LOG::MSG_DEBUG,
                                "Successfully completed insertOutputFile for RESULT #%u\n",
                                canonical_result.id
                        );
		}

		if( assimilation_handler->insertDataRows( result_data, canonical_result, jobID )==0 )
		{
                        log_messages.printf
                        (
                                SCHED_MSG_LOG::MSG_CRITICAL,
                                "Unable to complete insertDataRows for RESULT #%u\n",
                                canonical_result.id
                        );
		}
                else
                {
                        log_messages.printf
                        (
                                SCHED_MSG_LOG::MSG_DEBUG,
                                "Successfully completed insertDataRows for RESULT #%u\n",
                                canonical_result.id
                        );
                }

		
		if( assimilation_handler->insertCoefficients( result_data, canonical_result, jobID )==0 )
		{
                        log_messages.printf
                        (
                                SCHED_MSG_LOG::MSG_CRITICAL,
                                "Unable to complete insertCoefficients for RESULT #%u\n",
                                canonical_result.id
                        );
		}
                else
                {
                        log_messages.printf
                        (
                                SCHED_MSG_LOG::MSG_DEBUG,
                                "Successfully completed insertCoefficients for RESULT #%u\n",
                                canonical_result.id
                        );
                }


		//free memory
		delete xml_handler;
		delete assimilation_handler;
		delete result_data;
		
		return 0;
	}
}
